

namespace pyBind{

	template<typename ArgSq,typename beginIt,bool end = false>
	struct ArgFormatString
	{

		typedef typename fusion::result_of::deref<beginIt>::type valT_0;
		typedef typename remove_reference<valT_0>::type   valTr_0 ;

		typedef typename fusion::result_of::next<beginIt>::type itT_next;
		typedef typename fusion::result_of::end<ArgSq>::type itT_end;
		void operator()(std::string&str) 
		{
			str += valTr_0::PyArgStr();
			ArgFormatString<ArgSq,itT_next,is_same<itT_next, itT_end>::value >()(str);
		}
	};
	template<typename ArgSq,typename beginIt>
	struct ArgFormatString<ArgSq,beginIt,true>
	{
		void operator()(std::string&) 
		{
		}
	};

	//PyArg_ParseTuple

	template<typename ArgSq,int n>
	struct PyArg_ParseTupleT_n
	{
	};
	template<typename ArgSq>
	struct PyArg_ParseTupleT_n<ArgSq,0>
	{
		int operator()(ArgSq&,PyObject *)
		{
			return 1;
		}
	};
	
	template<typename ArgSq>
	struct PyArg_ParseTupleT_n<ArgSq,1>
	{

		typedef typename fusion::result_of::begin<ArgSq>::type itT_0;
		typedef typename fusion::result_of::deref<itT_0>::type valT_0;
		typedef typename remove_reference<valT_0>::type   valTr_0 ;

		int operator()(ArgSq& margs,PyObject *args)
		{
			itT_0 it0 = fusion::begin(margs);
			valT_0 val0 = fusion::deref(it0);

			int re = PyArg_ParseTuple(args,val0.PyArgStr(),&val0.pyval);
			if(!re)
				return re;
			val0.PyValueToTkValue();
	
			return re;
		}
	};

	template<typename ArgSq>
	struct PyArg_ParseTupleT_n<ArgSq,2>
	{

		typedef typename fusion::result_of::begin<ArgSq>::type itT_0;
		typedef typename fusion::result_of::deref<itT_0>::type valT_0;
		typedef typename remove_reference<valT_0>::type   valTr_0 ;

		typedef typename fusion::result_of::next<itT_0>::type itT_1;
		typedef typename fusion::result_of::deref<itT_1>::type valT_1;
		typedef typename remove_reference<valT_1>::type   valTr_1 ;

		int operator()(ArgSq& margs,PyObject *args)
		{
			itT_0 it_0 = fusion::begin(margs);
			valT_0 val0 = fusion::deref(it_0);
			itT_1 it_1 = fusion::next(it_0);
			valT_1 val1 =  fusion::deref(it_1);

			std::string passtr; 
			ArgFormatString<ArgSq,itT_0>()(passtr);
			int re = PyArg_ParseTuple(args,passtr.c_str(),&val0.pyval,&val1.pyval);
			if(!re)
				return re;

			val0.PyValueToTkValue();
			val1.PyValueToTkValue();

			return re;
		}
	};
	template<typename ArgSq>
	struct PyArg_ParseTupleT_n<ArgSq,3>
	{

		typedef typename fusion::result_of::begin<ArgSq>::type itT_0;
		typedef typename fusion::result_of::deref<itT_0>::type valT_0;
		typedef typename remove_reference<valT_0>::type   valTr_0 ;

		typedef typename fusion::result_of::next<itT_0>::type itT_1;
		typedef typename fusion::result_of::deref<itT_1>::type valT_1;
		typedef typename remove_reference<valT_1>::type   valTr_1 ;

		typedef typename fusion::result_of::next<itT_1>::type itT_2;
		typedef typename fusion::result_of::deref<itT_2>::type valT_2;
		typedef typename remove_reference<valT_2>::type   valTr_2 ;

		int operator()(ArgSq& margs,PyObject *args)
		{
			itT_0 it_0 = fusion::begin(margs);
			valT_0 val0 = fusion::deref(it_0);
			itT_1 it_1 = fusion::next(it_0);
			valT_1 val1 =  fusion::deref(it_1);
			itT_2 it_2 = fusion::next(it_1);
			valT_2 val2 =  fusion::deref(it_2);

			std::string passtr; 
			ArgFormatString<ArgSq,itT_0>()(passtr);
			int re = PyArg_ParseTuple(args,passtr.c_str(),&val0.pyval,&val1.pyval,&val2.pyval);
			if(!re)
				return re;

			val0.PyValueToTkValue();
			val1.PyValueToTkValue();
			val2.PyValueToTkValue();

			return re;
		}
	};
	template<typename ArgSq>
	struct PyArg_ParseTupleT_n<ArgSq,4>
	{

		typedef typename fusion::result_of::begin<ArgSq>::type itT_0;
		typedef typename fusion::result_of::deref<itT_0>::type valT_0;
		typedef typename remove_reference<valT_0>::type   valTr_0 ;

		typedef typename fusion::result_of::next<itT_0>::type itT_1;
		typedef typename fusion::result_of::deref<itT_1>::type valT_1;
		typedef typename remove_reference<valT_1>::type   valTr_1 ;

		typedef typename fusion::result_of::next<itT_1>::type itT_2;
		typedef typename fusion::result_of::deref<itT_2>::type valT_2;
		typedef typename remove_reference<valT_2>::type   valTr_2 ;

		typedef typename fusion::result_of::next<itT_2>::type itT_3;
		typedef typename fusion::result_of::deref<itT_3>::type valT_3;
		typedef typename remove_reference<valT_3>::type   valTr_3 ;

		int operator()(ArgSq& margs,PyObject *args)
		{
			itT_0 it_0 = fusion::begin(margs);
			valT_0 val0 = fusion::deref(it_0);
			itT_1 it_1 = fusion::next(it_0);
			valT_1 val1 =  fusion::deref(it_1);
			itT_2 it_2 = fusion::next(it_1);
			valT_2 val2 =  fusion::deref(it_2);
			itT_3 it_3 = fusion::next(it_2);
			valT_3 val3 =  fusion::deref(it_3);

			std::string passtr; 
			ArgFormatString<ArgSq,itT_0>()(passtr);
			int re = PyArg_ParseTuple(args,passtr.c_str(),&val0.pyval,&val1.pyval,&val2.pyval,&val3.pyval);
			if(!re)
				return re;

			val0.PyValueToTkValue()	;
			val1.PyValueToTkValue()	;
			val2.PyValueToTkValue()	;
			val3.PyValueToTkValue()	;

			return re;
		}
	};
	template<typename ArgSq>
	struct PyArg_ParseTupleT_n<ArgSq,5>
	{

		typedef typename fusion::result_of::begin<ArgSq>::type itT_0;
		typedef typename fusion::result_of::deref<itT_0>::type valT_0;
		typedef typename remove_reference<valT_0>::type   valTr_0 ;

		typedef typename fusion::result_of::next<itT_0>::type itT_1;
		typedef typename fusion::result_of::deref<itT_1>::type valT_1;
		typedef typename remove_reference<valT_1>::type   valTr_1 ;

		typedef typename fusion::result_of::next<itT_1>::type itT_2;
		typedef typename fusion::result_of::deref<itT_2>::type valT_2;
		typedef typename remove_reference<valT_2>::type   valTr_2 ;

		typedef typename fusion::result_of::next<itT_2>::type itT_3;
		typedef typename fusion::result_of::deref<itT_3>::type valT_3;
		typedef typename remove_reference<valT_3>::type   valTr_3 ;

		typedef typename fusion::result_of::next<itT_3>::type itT_4;
		typedef typename fusion::result_of::deref<itT_4>::type valT_4;
		typedef typename remove_reference<valT_4>::type   valTr_4 ;

		int operator()(ArgSq& margs,PyObject *args)
		{
			itT_0 it_0 = fusion::begin(margs);
			valT_0 val0 = fusion::deref(it_0);
			itT_1 it_1 = fusion::next(it_0);
			valT_1 val1 =  fusion::deref(it_1);
			itT_2 it_2 = fusion::next(it_1);
			valT_2 val2 =  fusion::deref(it_2);
			itT_3 it_3 = fusion::next(it_2);
			valT_3 val3 =  fusion::deref(it_3);
			itT_4 it_4 = fusion::next(it_3);
			valT_4 val4 =  fusion::deref(it_4);

			std::string passtr; 
			ArgFormatString<ArgSq,itT_0>()(passtr);
			int re = PyArg_ParseTuple(args,passtr.c_str(),&val0.pyval,&val1.pyval,&val2.pyval,&val3.pyval,&val4.pyval);
			if(!re)
				return re;

			val0.PyValueToTkValue()	;
			val1.PyValueToTkValue()	;
			val2.PyValueToTkValue()	;
			val3.PyValueToTkValue()	;
			val4.PyValueToTkValue()	;

			return re;
		}
	};


	template<typename ArgSq,typename beginIt,bool end = false,int tupleid = 0>
	struct PyArg_ParseTupleT_NN_e
	{

		typedef typename fusion::result_of::deref<beginIt>::type valT_0;

		typedef typename fusion::result_of::next<beginIt>::type itT_next;
		typedef typename fusion::result_of::end<ArgSq>::type itT_end;
		int operator()(ArgSq& margs,beginIt& it,PyObject *args) 
		{
			
			valT_0 val0 = fusion::deref(it);
			itT_next it_ne = fusion::next(it);

#ifdef _DEBUG
			int id =  tupleid;
#endif // _DEBUG

			val0.pyval = PyTuple_GetItem(args, tupleid);
			val0.PyValueToTkValue()	;

			return PyArg_ParseTupleT_NN_e<ArgSq,itT_next,is_same<itT_next, itT_end>::value, tupleid+1>()(margs,it_ne,args);
		}
	};
	template<typename ArgSq,typename beginIt,int tupleid>
	struct PyArg_ParseTupleT_NN_e<ArgSq,beginIt,true,tupleid>
	{
		int operator()(ArgSq&,beginIt&,PyObject*) 
		{
			return 1;
		}
	};



	template<typename ArgSq>
	struct PyArg_ParseTupleT_NN
	{

		typedef typename fusion::result_of::begin<ArgSq>::type itT_0;
		typedef typename fusion::result_of::end<ArgSq>::type itT_end;
		int operator()(ArgSq& margs,PyObject *args)
		{
			itT_0 it_0 = fusion::begin(margs);
			return PyArg_ParseTupleT_NN_e<ArgSq,itT_0,is_same<itT_0, itT_end>::value,0>()(margs,it_0,args);
		}
	};

	template<typename ArgSq,int n>
	struct PyArg_ParseTupleT_nn
		:PyArg_ParseTupleT_NN<ArgSq>
	{
	};
	template<typename ArgSq>
	struct PyArg_ParseTupleT_nn<ArgSq,0>
	{
		int operator()(ArgSq&,PyObject *)
		{
			return 1;
		}
	};

	template<typename ArgSq>
	struct PyArg_ParseTupleT
		:PyArg_ParseTupleT_nn<ArgSq, fusion::result_of::size<ArgSq>::type::value>
		//:PyArg_ParseTupleT_n<ArgSq, fusion::result_of::size<ArgSq>::type::value>
	{
	};


}	//end of namespace  pyBind